
#include <cmath>

#include <cairo/cairo.h>
#include <iostream>
#include <gtk/gtk.h>

#include "core/Thread.h"
#include "core/EventLoop.h"
#include "core/Action.h"

#include "ui/Window.h"
#include "ui/Event.h"

#include "ui/WidgetRoot.h"
#include "ui/WidgetButton.h"

#include "ui/Canvas.h"

#include "core/StringBuilder.h"

using namespace tbt;

void RoundRectPath(fx::Context* c, const DRect& r, double radius) {
	c->newPath();
	c->moveTo(DVec(r.x(), r.y()+radius));
	c->arc(DVec(r.x()+radius, r.y()+radius), radius, PI, 3*PI/2);
	c->lineTo(DVec(r.x() + r.width() - radius, r.y()));
	c->arc(DVec(r.x()+r.width()-radius, r.y()+radius), radius, 3*PI/2, 2*PI);
	c->lineTo(DVec(r.x() + r.width(), r.y() + r.height() - radius));
	c->arc(DVec(r.x()+r.width()-radius, r.y()+r.height()-radius), radius, 0, PI/2);
	c->lineTo(DVec(r.x()+radius, r.y()+r.height()));
	c->arc(DVec(r.x()+radius, r.y()+r.height()-radius), radius, PI/2, PI);
	c->closePath();
}

class RectWidget: public Widget {
public:
	RectWidget(): mLastMouseoverRect(0, 0, 20, 20) {}

protected:
	void onPaint(const IRect& r, fx::Context* cr) {
		DRect mr = getBounds().to<double>();
		cr->save();

//		//zero out the area
//		cr->rectangle(mr.to<double>());
//		cr->clip();
//		cr->setOperator(fx::Context::kOpSource);
//		cr->setSourceColor(0.0, 0.0, 0.0, 0.0);
//		cr->paint();
//
//		//draw the background
//		cr->setSourceColor(1.0, 1.0, 1.0);
//		cr->setOperator(fx::Context::kOpSource);
//		RoundRectPath(cr, mr, 4);
//		cr->fill();

		//draw square
		cr->setOperator(fx::Context::kOpOver);
		cr->rectangle(mLastMouseoverRect.to<double>());
		cr->clip();
		cr->setSourceColor(1.0, 0.0, 0.0);
		//cr->paint();
		//
		cr->restore();
//		std::cout << "Paint<" << r.x( )<< ", " << r.y() << ", "
//					<< r.width() << ", " << r.height() << "> " <<
//					"Pos<" << mLastMouseoverRect.position().x() << ", " <<
//								mLastMouseoverRect.position().y() << ">\n";
	}

	void onEvent_Motion(const MouseEvent& e) {
		IRect newRect(e.getPos(), IVec(20, 20));
		//std::cout << "Old: " << mLastMouseoverRect << ", New: " << newRect << "\n";
		auto updateRect = Rect<int>::Union(newRect, mLastMouseoverRect);
		mLastMouseoverRect = newRect;
		getRoot()->performPaint(updateRect, getRoot()->getContext());
	}

	void onEvent_Button(const MouseButtonEvent& e) {
		if (e.getType() == Event::kEvtMouseDown) {
			if (e.getButton() == Mouse::kButtonRight)
				EventLoop::current()->stopSoon();
			else if (e.getButton() == Mouse::kButtonLeft)
				getRoot()->getWindow()->beginWindowDrag(e.getButton(), e.getPos().x(), e.getPos().y());
		}
	}
private:
	IRect mLastMouseoverRect;
	static DVec mSqSize;
};

DVec RectWidget::mSqSize(20, 20);

class TaskGtkIteration: public Task {
public:
	virtual bool tick(Time t) {
		gtk_main_iteration_do(false);
		return false;
	}
};

class WidgetButtonClose: public WidgetButton {
public:
	WidgetButtonClose() {
		setText("x");
		setFontSize(16);
		setTextColor(fx::Color::White);
		setBackgroundColor(fx::Color(1.0, 0.0, 0.0));
	}
	void onEvent_Button(const MouseButtonEvent& e) {
		WidgetButton::onEvent_Button(e);
		if (e.getType() == Event::kEvtMouseDown && e.getButton() == Mouse::kButtonLeft) {
			EventLoop::current()->stopSoon();
		}
	}
};

int main(int argc, char* argv[]) {
	gtk_init(&argc, &argv);

	Ref<EventLoop> mainLoop = new EventLoop();
	mainLoop->addTask(new TaskGtkIteration());

	Ref<Window> mainWindow = new Window(WindowSettings(600, 400, "Hello, World!", false));
	Ref<WidgetRoot> rootWidget = new WidgetRoot();
	mainWindow->setRootWidget(rootWidget);

	rootWidget->addContent(new RectWidget());
	for (int i = 0; i < 4; ++i) {
		for (int j = 0; j < 4; ++j) {
			Ref<WidgetButton> bn = new WidgetButton();
			if ((i+j) % 2 == 0)
				bn->setBackgroundColor(fx::Color(238.0/255.0, 235.0/255.0, 231.0/255.0));
			else
				bn->setBackgroundColor(fx::Color(171.0/255.0, 141.0/255.0, 125.0/255.0));
			bn->setDesiredSize(IVec(96, 28));
			bn->setDesiredPosition(IVec(16 + 128*i, 52 + 64*j));
			bn->setText(StringBuilder() << "CLICK " << i << ", " << j);
			bn->setFontSize(14);
			bn->setTextColor(fx::Color::Black);
			rootWidget->addContent(bn);
		}
	}
	Ref<WidgetButton> close = new WidgetButtonClose();
	close->setDesiredSize(IVec(20, 20));
	close->setDesiredPosition(IVec(4, 4));
	rootWidget->addContent(close);

	rootWidget->performLayout();

	mainLoop->run();

	return 0;
}






























